/**
 * 枚举 enum
 * 和 JavaScript 中现有的概念对比，最贴切的可能就是 constants常量 文件
*/
//js
export default {
    Home_Page_Url: "url1",
    Setting_Page_Url: "url2",
    Share_Page_Url: "url3",
}
//把这段代码替换为 枚举，会是如下的形式：
enum PageUrl {
    Home_Page_Url = "url1",
    Setting_Page_Url = "url2",
    Share_Page_Url = "url3",
}
const home = PageUrl.Home_Page_Url;

/**
 * 使用枚举的好处：
 * 首先，有了更好的类型提示。
 * 其次，这些常量被真正地约束在一个 命名空间 下（上面的对象声明总是差点意思）。
 * 如果没有声明枚举的值，它会默认使用数字枚举，并且从 0 开始，以 1 递增：
 */
enum Items {
    Foo,
    Bar,
    Baz
}
//如果只为某一个成员指定了枚举值，那么之前未赋值成员仍然会使用从 0 递增的方式，之后的成员则会开始从枚举值递增。
enum ItemsA {
    // 0 
    FooA,
    BarA = 599,
    // 600
    BazA
}

/**
 * 在数字型枚举中，可以使用 延迟求值的枚举值
 * 但要注意，延迟求值的枚举值是有条件的。
 * 如果使用了延迟求值，那么 没有使用延迟求值的枚举成员 必须放在使用 常量枚举值声明的成员之后，或者放在第一位：
*/
//没有使用延迟求值的枚举成员(Baz) 必须放在使用 常量枚举值声明的成员之后
const returnNum = () => 100 + 499;
enum ItemsB {
    Foo = returnNum(),
    Bar = 599,
    Baz
}
//没有使用延迟求值的枚举成员(Baz) 放在第一位
enum ItemsC {
    Baz,
    Foo = returnNum(),
    Bar = 599,
}

//在 TypeScript 中也可以同时使用字符串枚举值和数字枚举值：
enum Mixed {
    Num = 599,
    Str = "hanxuming"
}

/*
 * 仅有值为数字的枚举成员 能够进行的双向枚举
 *
 * 在 仅有值为数字的枚举成员 的情况下，枚举和对象的重要差异在于：
 * 对象是单向映射的，我们只能从键映射到键值。
 * 而此种枚举是双向映射的，即可以从枚举成员映射到枚举值，也可以从枚举值映射到枚举成员：
 * 
 * 字符串枚举成员仍然只会进行单次映射
 */
enum ItemsD {
    Foo,
    Bar,
    Baz
}

const fooValue = ItemsD.Foo; // 0
const fooKey = ItemsD[0]; // "Foo"

/**
 * 常量枚举 const enum
 * 常量枚举 和 普通枚举 的差异：主要在访问性与编译产物。
 * 对于常量枚举，只能通过枚举成员访问枚举值（而不能通过值访问成员）。
 * 同时，在编译产物中并不会存在一个额外的辅助对象，对枚举成员的访问会被直接内联替换为枚举的值。
*/
const enum ItemsE {
    Foo,
    Bar,
    Baz
}
const fooValueA = ItemsE.Foo; // 0
//因为 对枚举成员的访问会被直接内联替换为枚举的值，所以以上的代码会被编译为如下形式：
//const fooValueA = 0 /* Foo */; // 0

//export {}：解决“无法重新声明块范围变量”错误提示问题
export { }